package com.example.prom.utils;

import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpVersion;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.entity.mime.FormBodyPart;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.ContentBody;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * NON-NLS
 */
@Slf4j
public class HttpNewUtils {

    /**
     * get
     *
     * @param host
     * @param path
     * @param headers
     * @param querys
     * @return
     * @throws Exception
     */
    public static HttpResponse doGet(String host, String path, HttpClient httpClient, Map<String, String> headers,
                                     Map<String, String> querys) throws Exception {
        if (headers == null) {
            headers = new HashMap<>();
        }

        String url = buildUrl(host, path, querys);
        log.info("HttpNewUtils get url:{}",url);
        HttpGet request = new HttpGet(url);
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        try {
            return httpClient.execute(request);
        } finally {
            request.abort();
        }
    }


    /**
     * Post json
     *
     * @param host
     * @param path
     * @param httpClient
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPostByJson(String host, String path, HttpClient httpClient, Map<String, String> headers,
                                            Map<String, String> querys, String body) throws Exception {

        if (headers == null) {
            headers = new HashMap<>();
        }

        String url = buildUrl(host, path, querys);
        HttpPost request = new HttpPost(url);
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (StringUtils.isNotBlank(body)) {
            request.setEntity(new StringEntity(body, "utf-8"));
        }

        return httpClient.execute(request);
    }

    public static HttpResponse doPostByApplicationJson(String host, String path, HttpClient httpClient, Map<String, String> headers,
                                                       Map<String, String> querys, String body) throws Exception {
        if (headers == null) {
            headers = new HashMap<>();
        }

        HttpResponse httpResponse;
        HttpPost request;

        String url = buildUrl(host, path, querys);
        request = new HttpPost(url);
        request.setProtocolVersion(HttpVersion.HTTP_1_0);
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        if (StringUtils.isNotBlank(body)) {
            StringEntity stringEntity = new StringEntity(body, ContentType.APPLICATION_JSON);
            request.setEntity(stringEntity);
        }

        httpResponse = httpClient.execute(request);

        return httpResponse;
    }

    /**
     * Post form
     *
     * @param host
     * @param path
     * @param httpClient
     * @param headers
     * @param querys
     * @param bodys
     * @return
     * @throws Exception
     */
    public static HttpResponse doPostByForm(String host, String path, HttpClient httpClient, Map<String, String> headers,
                                            Map<String, String> querys, Map<String, String> bodys) throws Exception {

        if (headers == null) {
            headers = new HashMap<>();
        }

        String url = buildUrl(host, path, querys);
        HttpPost request = new HttpPost(url);
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (bodys != null) {
            final List<NameValuePair> nameValuePairList = new ArrayList<>();

            for (final String key : bodys.keySet()) {
                nameValuePairList.add(new BasicNameValuePair(key, bodys.get(key)));
            }
            final UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(nameValuePairList, "utf-8");
//            formEntity.setContentType("application/x-www-form-urlencoded; charset=UTF-8");
            request.setEntity(formEntity);
        }

        return httpClient.execute(request);
    }

    public static HttpResponse doPostByFormData(String host, String path, HttpClient httpClient, Map<String, String> headers,
                                                Map<String, String> querys, Map<String, Map<String, Object>> bodys,Map<String, File> files) throws Exception {

        if (headers == null) {
            headers = new HashMap<>();
        }

        String url = buildUrl(host, path, querys);

        HttpPost request = new HttpPost(url);
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        MultipartEntityBuilder reqEntity = MultipartEntityBuilder.create();
        if (bodys != null) {
            for (Map.Entry<String,Map<String, Object>> entry : bodys.entrySet()) {
                reqEntity.addTextBody(entry.getKey(), JSONObject.toJSONString(entry.getValue()), ContentType.MULTIPART_FORM_DATA);
            }
        }
        if(files != null){
            for (Map.Entry<String,File> entry : files.entrySet()) {
                FileBody file = new FileBody(entry.getValue());
                reqEntity.addPart(entry.getKey(), file);
            }
        }

        request.setEntity(reqEntity.build());
        return httpClient.execute(request);
    }

    public static HttpResponse doPostByFormFile(String host, String path, HttpClient httpClient, Map<String, String> headers,
                                            Map<String, String> querys, Map<String, String> bodys, MultipartFile file) throws Exception {

        if (headers == null) {
            headers = new HashMap<>();
        }

        String url = buildUrl(host, path, querys);
        HttpPost request = new HttpPost(url);
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        if(file != null){
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            String filename = file.getOriginalFilename();
            builder.setCharset(StandardCharsets.UTF_8);
//            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
//            builder.setContentType(ContentType.MULTIPART_FORM_DATA.withCharset("utf-8"));
            builder.addBinaryBody("file", file.getBytes(), ContentType.MULTIPART_FORM_DATA, filename);
            if (bodys != null) {
                // 如果需要，传递额外参数
                // StringBody fileName = new StringBody("文件名称", ContentType.MULTIPART_FORM_DATA);
                // StringBody userName = new StringBody("用户名", ContentType.MULTIPART_FORM_DATA);
                // builder.addPart("fileName", fileName);
                // builder.addPart("userName", userName);
            }
            HttpEntity build = builder.build();
            request.setEntity(build);
        }

        return httpClient.execute(request);
    }

    public static File MultipartFileToFile(MultipartFile multiFile) {
        // 获取文件名
        String fileName = multiFile.getOriginalFilename() == null ? "123":multiFile.getOriginalFilename();
        // 获取文件后缀
        String prefix = fileName.substring(fileName.lastIndexOf("."));
        // 若须要防止生成的临时文件重复,能够在文件名后添加随机码

        try {
            File file = File.createTempFile(fileName, prefix);
            multiFile.transferTo(file);
            return file;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static HttpResponse doPostByFormFile(String host, String path, HttpClient httpClient, Map<String, String> headers,
                                                Map<String, String> querys, Map<String, String> bodys, File file) throws Exception {

        if (headers == null) {
            headers = new HashMap<>();
        }

        String url = buildUrl(host, path, querys);
        HttpPost request = new HttpPost(url);
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }
        if(file != null){
            MultipartEntityBuilder builder = MultipartEntityBuilder.create();
            builder.setCharset(StandardCharsets.UTF_8);
            builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
            builder.setContentType(ContentType.MULTIPART_FORM_DATA.withCharset("utf-8"));
            builder.addPart("file", new FileBody(file));
            if (bodys != null) {
                // 如果需要，传递额外参数
                // StringBody fileName = new StringBody("文件名称", ContentType.MULTIPART_FORM_DATA);
                // StringBody userName = new StringBody("用户名", ContentType.MULTIPART_FORM_DATA);
                // builder.addPart("fileName", fileName);
                // builder.addPart("userName", userName);
            }
            HttpEntity build = builder.build();
            request.setEntity(build);
        }

        return httpClient.execute(request);
    }

    /**
     * Post Text
     *
     * @param host
     * @param path
     * @param headers
     * @param querys
     * @param text
     * @return
     * @throws Exception
     */
    public static HttpResponse doPostByText(String host, String path, HttpClient httpClient, Map<String, String> headers,
                                            Map<String, String> querys, String text) throws Exception {

        if (headers == null) {
            headers = new HashMap<>();
        }

        String url = buildUrl(host, path, querys);

        HttpPost request = new HttpPost(url);
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (text != null) {
            StringEntity stringEntity = new StringEntity(text,"utf-8");
            request.setEntity(stringEntity);
        }

        return httpClient.execute(request);
    }

//    /**
//     * Post file
//     *
//     * @param host
//     * @param path
//     * @param headers
//     * @param querys
//     * @param bodys
//     * @param files
//     * @return
//     * @throws Exception
//     */
//    public static HttpResponse doPostByFile(String host, String path, HttpClient httpClient, Map<String, String> headers,
//                                            Map<String, String> querys, Map<String, String> bodys,Map<String, File> files) throws Exception {
//
//        if (headers == null) {
//            headers = new HashMap<>();
//        }
//
//        String url = buildUrl(host, path, querys);
//
//        HttpPost request = new HttpPost(url);
//        for (Map.Entry<String, String> e : headers.entrySet()) {
//            request.addHeader(e.getKey(), e.getValue());
//        }
//
//        MultipartEntityBuilder reqEntity = MultipartEntityBuilder.create();
//        if (bodys != null) {
//            for (Map.Entry<String,String> entry : bodys.entrySet()) {
//                StringBody value = new StringBody(entry.getValue(), ContentType.create("text/plain", Consts.UTF_8));
//                reqEntity.addPart(entry.getKey(), value);
//            }
//        }
//        if(files != null){
//            for (Map.Entry<String,File> entry : files.entrySet()) {
//                FileBody file = new FileBody(entry.getValue());
//                reqEntity.addPart(entry.getKey(), file);
//            }
//        }
//        request.setEntity(reqEntity.build());
//        return httpClient.execute(request);
//    }


//
//    /**
//     * Post formdata
//     *
//     * @param host
//     * @param path
//     * @param headers
//     * @param querys
//     * @param bodys
//     * @return
//     * @throws Exception
//     */
//    public static HttpResponse doPostByFormData(String host, String path, HttpClient httpClient, Map<String, String> headers,
//                                                Map<String, String> querys, Map<String, Map<String, Object>> bodys,Map<String, File> files) throws Exception {
//
//        if (headers == null) {
//            headers = new HashMap<>();
//        }
//
//        String url = buildUrl(host, path, querys);
//
//        HttpPost request = new HttpPost(url);
//        for (Map.Entry<String, String> e : headers.entrySet()) {
//            request.addHeader(e.getKey(), e.getValue());
//        }
//
//        MultipartEntityBuilder reqEntity = MultipartEntityBuilder.create();
//        if (bodys != null) {
//            for (Map.Entry<String,Map<String, Object>> entry : bodys.entrySet()) {
//                reqEntity.addTextBody(entry.getKey(), JSONObject.toJSONString(entry.getValue()), ContentType.MULTIPART_FORM_DATA);
//            }
//        }
//        if(files != null){
//            for (Map.Entry<String,File> entry : files.entrySet()) {
//                FileBody file = new FileBody(entry.getValue());
//                reqEntity.addPart(entry.getKey(), file);
//            }
//        }
//
//        request.setEntity(reqEntity.build());
//        return httpClient.execute(request);
//    }

    /**
     * Put json
     *
     * @param host
     * @param path
     * @param httpClient
     * @param headers
     * @param querys
     * @param body
     * @return
     * @throws Exception
     */
    public static HttpResponse doPutByJson(String host, String path, HttpClient httpClient, Map<String, String> headers,
                                           Map<String, String> querys, String body) throws Exception {

        if (headers == null) {
            headers = new HashMap<>();
        }

        String url = buildUrl(host, path, querys);
        HttpPut request = new HttpPut(url);
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (StringUtils.isNotBlank(body)) {
            request.setEntity(new StringEntity(body, "utf-8"));
        }

        return httpClient.execute(request);
    }

    public static HttpResponse doPutByApplicationJSON(String host, String path, HttpClient httpClient, Map<String, String> headers,
                                           Map<String, String> querys, String body) throws Exception {

        if (headers == null) {
            headers = new HashMap<>();
        }

        String url = buildUrl(host, path, querys);
        HttpPut request = new HttpPut(url);
        for (Map.Entry<String, String> e : headers.entrySet()) {
            request.addHeader(e.getKey(), e.getValue());
        }

        if (StringUtils.isNotBlank(body)) {
            request.setEntity(new StringEntity(body, ContentType.APPLICATION_JSON));
        }

        return httpClient.execute(request);
    }

    /**
     * 下载文件
     *
     * @param fileURL
     * @param file
     */
    public static void downLoadByFileUrl(String fileURL,HttpClient httpClient,File file,Map<String, String> headers){
        if (StringUtils.isEmpty(fileURL)) {
            return;
        }
        if (headers == null) {
            headers = new HashMap<>();
        }
        InputStream inStream = null;
        try(FileOutputStream outStream = new FileOutputStream(file)){
            log.info("downLoadByFileUrl url:{}" , fileURL);
            HttpGet request = new HttpGet(fileURL);
            for (Map.Entry<String, String> e : headers.entrySet()) {
                request.addHeader(e.getKey(), e.getValue());
            }
            HttpResponse httpResponse = httpClient.execute(request);

            inStream = httpResponse.getEntity().getContent();
            byte[] data = readInputStream(inStream);
            outStream.write(data);
        } catch (Exception e) {
            log.error("downLoadByFileUrl error",e);
        } finally {
            if(inStream != null){
                try {
                    inStream.close();
                } catch (IOException e) {
                    log.error("inStream error:",e);
                }
            }
        }
    }

    /**
     * 下载文件
     *
     * @param fileURL
     */
    public static InputStream downLoad4Stream(String fileURL,HttpClient httpClient,Map<String, String> headers){
        if (StringUtils.isEmpty(fileURL)) {
            return null;
        }
        if (Objects.isNull(headers)) {
            headers = new HashMap<>();
        }
        HttpResponse httpResponse = null;
        try {
            HttpGet request = new HttpGet(fileURL);
            for (Map.Entry<String, String> e : headers.entrySet()) {
                request.addHeader(e.getKey(), e.getValue());
            }

            httpResponse = httpClient.execute(request);
            return httpResponse.getEntity().getContent();
        } catch (Exception e) {
            log.error("downLoad request error:{}",e);
        }

        return null;
    }


    private static String buildUrl(String host, String path, Map<String, String> querys)
            throws UnsupportedEncodingException {

        StringBuilder sbUrl = new StringBuilder();
        sbUrl.append(host);
        if (!StringUtils.isBlank(path)) {
            sbUrl.append(path);
        }
        if (null != querys) {
            StringBuilder sbQuery = new StringBuilder();
            for (Map.Entry<String, String> query : querys.entrySet()) {
                if (0 < sbQuery.length()) {
                    sbQuery.append("&");
                }
                if (StringUtils.isBlank(query.getKey()) && !StringUtils.isBlank(query.getValue())) {
                    sbQuery.append(query.getValue());
                }
                if (!StringUtils.isBlank(query.getKey())) {
                    sbQuery.append(query.getKey());
                    if (!StringUtils.isBlank(query.getValue())) {
                        sbQuery.append("=");
                        sbQuery.append(URLEncoder.encode(query.getValue(), "utf-8"));
                    }
                }
            }
            if (0 < sbQuery.length()) {
                sbUrl.append("?").append(sbQuery);
            }
        }

        return sbUrl.toString();
    }

    public static HttpResponse downLoad(String fileURL,HttpClient httpClient,Map<String, String> headers){
        if (StringUtils.isEmpty(fileURL)) {
            return null;
        }
        if (Objects.isNull(headers)) {
            headers = new HashMap<>();
        }
        try {
            HttpGet request = new HttpGet(fileURL);
            for (Map.Entry<String, String> e : headers.entrySet()) {
                request.addHeader(e.getKey(), e.getValue());
            }

            HttpResponse httpResponse = httpClient.execute(request);
            return httpResponse;
        } catch (Exception e) {
            log.error("downLoad request error:{}",e);
        }

        return null;
    }

    private static byte[] readInputStream(InputStream inStream) throws Exception{
        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
        byte[] buffer = new byte[1536];
        int len = 0;
        while((len=inStream.read(buffer)) != -1){
            outStream.write(buffer, 0, len);
        }
        return outStream.toByteArray();
    }


}